/*
 * Copyright (C) 2015 yixun All Rights Reserved.
 *
 * AreaServiceImpl.java
 */
package com.yixun.qfbao.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.yixun.qfbao.api.service.*;
import com.yixun.qfbao.apidto.PremisesRecommenderDto;
import com.yixun.qfbao.apidto.*;
import com.yixun.qfbao.apidto.base.CommonResDTO;
import com.yixun.qfbao.config.M2ApiConfig;
import com.yixun.qfbao.config.V10ApiConfig;
import com.yixun.qfbao.constant.StringConstant;
import com.yixun.qfbao.dao.DepartmentDao;
import com.yixun.qfbao.model.Dictionary;
import com.yixun.qfbao.model.*;
import com.yixun.qfbao.model.dto.*;
import com.yixun.qfbao.model.enums.*;
import com.yixun.qfbao.service.CommissionService;
import com.yixun.qfbao.service.CompanyService;
import com.yixun.qfbao.service.DocumentService;
import com.yixun.qfbao.service.*;
import com.yixun.qfbao.util.*;
import com.yixun.qfbao.util.exception.TServerException;
import com.yixun.qfbao.xf.model.CaseMember;
import com.yixun.qfbao.xf.model.CustomerPremises;
import com.yixun.qfbao.xf.model.FollowUpList;
import com.yixun.qfbao.xf.model.Premises;
import com.yixun.qfbao.xf.model.dto.CaseMemberDto;
import com.yixun.qfbao.xf.model.dto.CustomerPremisesAffixDto;
import com.yixun.qfbao.xf.model.dto.CustomerPremisesDto;
import com.yixun.qfbao.xf.model.dto.FollowUpListDto;
import com.yixun.qfbao.xf.model.enums.CommissionStatusEnum;
import com.yixun.qfbao.xf.model.enums.*;
import com.yixun.qfbao.xf.service.CaseMemberService;
import com.yixun.qfbao.xf.service.CustomerPremisesService;
import com.yixun.qfbao.xf.service.FollowUpListService;
import com.yixun.qfbao.xf.service.PremisesService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * [文件名称]<br>
 * CPReportServiceImpl.java<br>
 * <br>checkOverdueConfigTip
 * [文件描述]<br>
 * 报备相关<br>
 * <br>
 *
 * @author JHSong
 * @version 1.00
 */
@Service
public class CPReportServiceImpl implements CPReportService {

    private Logger logger = LoggerFactory.getLogger(CPReportServiceImpl.class);

    @Autowired
    M2ApiConfig m2ApiConfig;
    @Autowired
    private SMSUtil smsUtil;
    @Autowired
    private ReportCommonService reportCommonService;
    @Autowired
    private AuditReportService auditReportService;
    @Autowired
    private PartnerInfoService partnerInfoService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private PremisesService premisesService;
    @Autowired
    private CustomerPremisesService customerPremisesService;
    @Autowired
    private FollowUpListService followUpListService;
    @Autowired
    private CaseMemberService caseMemberService;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private SmsHistoryService smsHistoryService;
    @Autowired
    private DocumentService documentService;
    @Autowired
    private CustomerInfoService customerInfoService;
    @Autowired
    private CommissionService commissionService;
    @Autowired
    private CommissionRuleParentService commissionRuleParentService;
    @Autowired
    private ReportVisitService reportVisitService;
    @Autowired
    private V10BindService v10BindService;
    @Autowired
    private AffixService affixService;
    @Autowired
    V10ApiConfig v10ApiConfig;
    @Autowired
    private ReportModelApiService reportModelApiService;
    @Autowired
    private WxTemplateMsgService wxTemplateMsgService;
    @Autowired
    private PremisesRecommenderService premisesRecommenderService;
    @Autowired
    private RoleResourcesService roleResourcesService;
    @Autowired
    private PremisesOverdueService premisesOverdueService;
	@Autowired
	private EstateAdviserService estateAdviserService;
	@Autowired
	private ReportCommissionService reportCommissionService;
    @Autowired
    private ReportCopyRecordService reportCopyRecordService;

    /**
     * 操作报备表、佣金表数据
     *
     * @param confirmStatus
     * @param cpDto
     * @param remark
     * @param partnerInfo
     * @param customerPremisesId
     */
    @Override
    public void operateCommission(String confirmStatus, CustomerPremisesDto cpDto, String remark, PartnerInfo partnerInfo, Long customerPremisesId) {
        ReportCommissionDto dto = new ReportCommissionDto();
        dto.setReportId(cpDto.getId());
        dto.setDelFlag(DelFlagEnum.UNDEL.getNo());
        ReportCommission reportCommission = reportCommissionService.selectOne(dto);
        if(reportCommission == null){
            reportCommission = new ReportCommission();
            reportCommission.setReportId(cpDto.getId());
        }
        //交易状态为已签约
        if (ConfirmStatusEnum.sign.getNo().equals(confirmStatus)) {
            // 机构ID
            Long companyId = cpDto.getStaffCompanyId();
            // 楼盘ID
            Long premisesId = cpDto.getPremisesId();
            // 获取当前的规则
            CommissionRules rule = customerInfoService.getNewCommission(companyId, premisesId, cpDto.getDealAmount(), true, "add");
            //没有规则，根据楼盘ID，机构ID以及佣金状态来判断是否有重复数据
            if (null == rule.getRelationId()) {
                CommissionDto cDto = new CommissionDto();
                cDto.setAgentCompanyId(companyId);
                cDto.setPremisesId(premisesId);
                cDto.setCommissionStatus(CommissionStatusEnum.no_commission.getNo());
                cDto.setSql("commission_rule_id is null");
                //没有规则，查询对应的佣金
                Commission commission = commissionService.selectByCompanyIdAndPremisesId(cDto);
				if (null == commission) {
					//添加佣金
					Long commissionId = addCommission(cDto, cpDto, remark, partnerInfo, null, null);
					//更新报备信息表里的佣金ID
					updateCustomerPremises(customerPremisesId, commissionId, null);
					reportCommission.setCommissionId(commissionId);
				} else {
					//更新佣金
					updateCommission(commission, cpDto, remark, partnerInfo, null, null);
					//更新报备信息表里的佣金ID
					updateCustomerPremises(customerPremisesId, commission.getId(), null);
					reportCommission.setCommissionId(commission.getId());
				}
				// 佣金规则状态，0:无规则，1有规则
				reportCommission.setRuleStatus("0");
			} else {
				//有规则
				CommissionRuleParent commissionRuleParent = commissionRuleParentService.selectById(rule.getRelationId());
				CommissionDto cDto = new CommissionDto();
				cDto.setAgentCompanyId(companyId);
				cDto.setPremisesId(premisesId);
				cDto.setBeginTime(commissionRuleParent.getBeginTime());
				cDto.setEndTime(commissionRuleParent.getEndTime());
				cDto.setCommissionRuleId(rule.getGroupId());
				cDto.setCommissionStatus(CommissionStatusEnum.no_commission.getNo());
				//有规则，查询对应的佣金
				Commission commission = commissionService.selectByCompanyIdAndPremisesId(cDto);
				if (null == commission) {
					//添加佣金
					Long commissionId = addCommission(cDto, cpDto, remark, partnerInfo, rule, commissionRuleParent);
					//更新报备信息表里的佣金ID
					updateCustomerPremises(customerPremisesId, commissionId, rule.getId());
					reportCommission.setCommissionId(commissionId);
				} else {
					//更新佣金
					updateCommission(commission, cpDto, remark, partnerInfo, rule, commissionRuleParent);
					//更新报备信息表里的佣金ID
					updateCustomerPremises(customerPremisesId, commission.getId(), rule.getId());
					reportCommission.setCommissionId(commission.getId());
				}
				reportCommission.setAgentCommission(new BigDecimal(rule.getCommissionAmmount()));
				reportCommission.setAgentPendingCommission(new BigDecimal(rule.getCommissionAmmount()));
				// 佣金规则状态，0:无规则，1有规则
				reportCommission.setRuleStatus("1");
			}
		}else if (ConfirmStatusEnum.sign_fail.getNo().equals(confirmStatus)) {
			// 机构ID
			Long companyId = cpDto.getStaffCompanyId();
			// 楼盘ID
			Long premisesId = cpDto.getPremisesId();
			// 获取当前的规则
			CommissionRules rule = customerInfoService.getNewCommission(companyId, premisesId, cpDto.getDealAmount(), true, "del");
			//没有规则，根据楼盘ID，机构ID以及佣金状态来判断是否有重复数据
			if (null == rule.getRelationId()) {
				CommissionDto cDto = new CommissionDto();
				cDto.setAgentCompanyId(companyId);
				cDto.setPremisesId(premisesId);
				cDto.setCommissionStatus(CommissionStatusEnum.no_commission.getNo());
				cDto.setSql("commission_rule_id is null");
				//没有规则，查询对应的佣金
				Commission commission = commissionService.selectByCompanyIdAndPremisesId(cDto);
				//新增
				if (null != commission) {
					//更新佣金
					delCommission(commission, cpDto, remark, partnerInfo, null, null);
				}
				// 佣金规则状态，0:无规则，1有规则
				reportCommission.setRuleStatus("0");
			} else {
				//有规则
				CommissionRuleParent commissionRuleParent = commissionRuleParentService.selectById(rule.getRelationId());
				CommissionDto cDto = new CommissionDto();
				cDto.setAgentCompanyId(companyId);
				cDto.setPremisesId(premisesId);
				cDto.setBeginTime(commissionRuleParent.getBeginTime());
				cDto.setEndTime(commissionRuleParent.getEndTime());
				cDto.setCommissionRuleId(rule.getGroupId());
				cDto.setCommissionStatus(CommissionStatusEnum.no_commission.getNo());
				//有规则，查询对应的佣金
				Commission commission = commissionService.selectByCompanyIdAndPremisesId(cDto);
				if (null != commission) {
					//更新佣金
					delCommission(commission, cpDto, remark, partnerInfo, rule, commissionRuleParent);
				}
				// 佣金规则状态，0:无规则，1有规则
				reportCommission.setRuleStatus("0");
			}
			// 退房清零开发商和合作机构总佣金和代结佣金
			reportCommission.setAgentPendingCommission(BigDecimal.ZERO);
			reportCommission.setAgentCommission(BigDecimal.ZERO);
			reportCommission.setDevPendingCommission(BigDecimal.ZERO);
			reportCommission.setDevCommission(BigDecimal.ZERO);
		}
		reportCommissionService.saveOrUpdateForReport(reportCommission,cpDto,partnerInfo.getId());
	}

    /**
     * 添加佣金
     *
     * @param cDto
     * @param customerPremisesDto
     * @param remark
     * @param partnerInfo
     * @param rule
     * @param pRule
     * @return
     * @author shaoping.jiao
     */
    private Long addCommission(CommissionDto cDto, CustomerPremisesDto customerPremisesDto, String remark, PartnerInfo partnerInfo, CommissionRules rule, CommissionRuleParent pRule) {
        if (null != rule) {
            //从规则子表里取结算周期
            cDto.setSettlementCycle(rule.getSettlementCycle());
            //待结算日期
            cDto.setPendingDate(pRule.getEndTime());
            cDto.setCommissionRuleId(rule.getGroupId());
            cDto.setPendingCommission(rule.getCommissionAmmount());
        } else {
            //待结算佣金  此处0改为空是为了区别设置了佣金但是没有报备时佣金为0的情况。为空则表明该楼盘未给该机构设置佣金规则
            cDto.setPendingCommission("");
        }
        //初次新增，套数固定为1，以后累加。
        cDto.setDealNum("1");
        //初次的成交金额为页面填写的成交金额
        cDto.setDealAmount(customerPremisesDto.getDealAmount().toString());
        cDto.setReason(remark);
        //佣金类型，现在只有一种 0 - 佣金机构
        cDto.setType("0");
        //创建人ID
        cDto.setCreateUserId(partnerInfo.getId());
        cDto.setCreateTime(Calendar.getInstance().getTime());
        //删除状态 0 - 否
        cDto.setDelFlag("0");
        //开发商ID
        cDto.setDevCompanyId(partnerInfo.getHigherid());
        commissionService.add(cDto);
        return cDto.getId();
    }

    /**
     * 更新佣金表里的信息
     *
     * @param commission
     * @param customerPremisesDto
     * @param remark
     * @param partnerInfo
     * @param rule
     * @param pRule
     * @return
     * @author shaoping.jiao
     */
    private int updateCommission(Commission commission, CustomerPremisesDto customerPremisesDto, String remark, PartnerInfo partnerInfo, CommissionRules rule, CommissionRuleParent pRule) {
        Commission cn = new Commission();
        //如果有规则需要多更新以下几条信息
        if (null != rule) {
            //经确认，计算佣金的时候不计算当次的数据
            //如果要计算当次，需要修改customerInfoService.getNewCommission方法加相应的标识，
            //在获取总套数和总金额的时候，加上本次即可。
            cn.setPendingCommission(rule.getCommissionAmmount());
            cn.setBeginTime(pRule.getBeginTime());
            cn.setEndTime(pRule.getEndTime());
        }
        cn.setDealNum(String.valueOf(Long.parseLong(commission.getDealNum()) + 1));
        cn.setDealAmount(String.valueOf(new BigDecimal(commission.getDealAmount()).add(customerPremisesDto.getDealAmount())));
        cn.setReason(remark);
        cn.setUpdateUserId(partnerInfo.getId());
        cn.setUpdateTime(Calendar.getInstance().getTime());
        cn.setId(commission.getId());
        return commissionService.edit(cn);
    }

    /**
     * 更新佣金表里的信息
     * 退房时扣掉佣金
     *
     * @param commission
     * @param customerPremisesDto
     * @param remark
     * @param partnerInfo
     * @param rule
     * @param pRule
     * @return
     * @author shaoping.jiao
     */
    private int delCommission(Commission commission, CustomerPremisesDto customerPremisesDto, String remark, PartnerInfo partnerInfo, CommissionRules rule, CommissionRuleParent pRule) {
        Commission cn = new Commission();
        //如果有规则需要多更新以下几条信息
        if (null != rule) {
            //经确认，计算佣金的时候不计算当次的数据
            //如果要计算当次，需要修改customerInfoService.getNewCommission方法加相应的标识，
            //在获取总套数和总金额的时候，加上本次即可。
            cn.setPendingCommission(rule.getCommissionAmmount());
            cn.setBeginTime(pRule.getBeginTime());
            cn.setEndTime(pRule.getEndTime());
        }
        cn.setDealNum(String.valueOf(Long.parseLong(commission.getDealNum())));
        cn.setDealAmount(String.valueOf(new BigDecimal(commission.getDealAmount()).subtract(customerPremisesDto.getDealAmount() == null ? BigDecimal.ZERO : customerPremisesDto.getDealAmount())));
        cn.setReason(remark);
        cn.setUpdateUserId(partnerInfo.getId());
        cn.setUpdateTime(Calendar.getInstance().getTime());
        cn.setId(commission.getId());
        int count = commissionService.edit(cn);

        /**
         * 修改报备结佣状态为退房
         */
        CustomerPremisesDto cusPreDto = new CustomerPremisesDto();
        cusPreDto.setId(customerPremisesDto.getId());
        cusPreDto.setCommissionStatus(CommissionStatusEnum.out_commission.getNo());
        customerPremisesService.update(cusPreDto);

        return count;
    }

    private int updateCustomerPremises(Long customerPremisesId, Long commissionId, Long rulesId) {
        CustomerPremisesDto cpDto = new CustomerPremisesDto();
        cpDto.setId(customerPremisesId);
        cpDto.setCommissionId(commissionId);
        cpDto.setRulesId(rulesId);
        return customerPremisesService.update(cpDto);
    }

    @Override
    public DistCPAgentResDto distCPAgent(DistCPAgentReqDto reqDto) {
        DistCPAgentResDto resDto = new DistCPAgentResDto();
        resDto.setResult(ResultEnum.FAIL.getNo());
        try {
            //1、判断记录是否存在
            //2、修改报备状态
            //3、添加跟进
            CustomerPremises cusPre = customerPremisesService.selectById(Long.valueOf(reqDto.getCusPreId()));
            if (null == cusPre) {
                resDto.setResultMsg("报备记录不存在!");
                return resDto;
            }

            String currStatus = cusPre.getCustomerStatus();
            Long partnerId = cusPre.getPartnerId();
            if (CustomerStatusEnum.has_visited.getNo().equals(currStatus)) {
                if (null != partnerId) {
                    PartnerInfo pi = partnerInfoService.selectById(partnerId);
                    resDto.setResultMsg("该报备已分配给" + pi.getAccountName() + ",不能再次分配!");
                    return resDto;
                }
            } else {
                resDto.setResultMsg("报备未到访,不能分配经纪人!");
                return resDto;
            }
            PartnerInfo agentPi = partnerInfoService.selectById(Long.valueOf(reqDto.getPartnerId()));
            if (null == agentPi) {
                resDto.setResultMsg("待分配案场经纪人不存在!");
                return resDto;
            }
            if ("0".equals(agentPi.getStatus())) {
                resDto.setResultMsg("无效案场人员,不能分配!");
                return resDto;
            }

            CustomerPremisesDto cusPreDto = new CustomerPremisesDto();
            cusPreDto.setId(cusPre.getId());
            cusPreDto.setPartnerId(Long.valueOf(reqDto.getPartnerId()));
            cusPreDto.setCompanyId(agentPi.getHigherid());
            int updateCount = customerPremisesService.update(cusPreDto);
            if (updateCount > 0) {
                //添加跟进记录
                FollowUpListDto fulDto = new FollowUpListDto();
                fulDto.setCreateTime(Calendar.getInstance().getTime());
                fulDto.setCustomerPremisesId(cusPre.getId());
                fulDto.setOldConfirmStatus(cusPre.getConfirmStatus());
                fulDto.setNewConfirmStatus(cusPre.getConfirmStatus());
                fulDto.setOldCustomerStatus(cusPre.getCustomerStatus());
                fulDto.setNewCustomerStatus(cusPre.getCustomerStatus());
                fulDto.setStaffId(cusPre.getStaffId());
                fulDto.setFollowType(FollowTypeEnum.DEVELOPERS.getNo());
                fulDto.setRemark("【分配经纪人】 分配经纪人");
                fulDto = followUpListService.create(fulDto);

                resDto.setResult(ResultEnum.SUCCESS.getNo());
                resDto.setResultMsg("分配案场经纪人成功!");
            } else {
                resDto.setResultMsg("分配案场经纪人失败!");
            }
        } catch (Exception ex) {
            logger.error("分配案场经纪人失败: {}", ex);
            resDto.setResultMsg("分配案场经纪人失败: " + ex.getMessage());
        }
        return resDto;
    }

    @Override
    public EditCPCusInfoResDto editCPCusInfo(EditCPCusInfoReqDto reqDto) {
        EditCPCusInfoResDto resDto = new EditCPCusInfoResDto();
        resDto.setResult(ResultEnum.FAIL.getNo());
        try {
            CustomerPremises cp = customerPremisesService.selectById(Long.parseLong(reqDto.getId()));
            if (null != cp) {
                if (cp == null) {
                    throw new TServerException("报备信息不存在！");
                }

                StringBuilder remark = new StringBuilder("【编辑客户】");
                if (!cp.getName().equals(reqDto.getName().trim())) {
                    remark.append("将客户姓名改为：" + reqDto.getName() + "，原客户姓名为：" + cp.getName() + "；");
                }
                if (!cp.getGender().equals(reqDto.getGender())) {
                    remark.append("将客户性别改为：" + GenderEnum.getDescByNo(reqDto.getGender()) + "，原客户性别为：" + GenderEnum.getDescByNo(cp.getGender()) + "；");
                }
                if (StringUtils.isNotBlank(reqDto.getRemark().trim()) && !Objects.equals(reqDto.getRemark().trim(), cp.getRemark())) {
                    remark.append("将客户意向改为：" + reqDto.getRemark() + "，原客户意向为：" + cp.getRemark() + "；");
                }

                //更新客户信息
                CustomerPremisesDto cpDto = new CustomerPremisesDto();
                cpDto.setId(cp.getId());
                cpDto.setName(reqDto.getName());
                cpDto.setGender(reqDto.getGender());
                cpDto.setRemark(reqDto.getRemark());
                customerPremisesService.update(cpDto);

                //添加修改记录
                FollowUpListDto followDto = new FollowUpListDto();
                followDto.setStaffId(Long.valueOf(reqDto.getUserId()));
                followDto.setCustomerPremisesId(Long.valueOf(reqDto.getId()));
                followDto.setOldConfirmStatus(cp.getConfirmStatus());
                followDto.setNewConfirmStatus(cp.getConfirmStatus());
                followDto.setOldCustomerStatus(cp.getCustomerStatus());
                followDto.setNewCustomerStatus(cp.getCustomerStatus());
                followDto.setRemark(remark.toString());
                followDto.setFollowUpType(FollowUpEnum.status_transfer.getNo());
                followDto.setFollowType(FollowTypeEnum.DEVELOPERS.getNo());
                followUpListService.create(followDto);

                resDto.setResult(ResultEnum.SUCCESS.getNo());
                resDto.setResultMsg("报备客户信息修改成功!");
            }
        } catch (Exception ex) {
            logger.error("报备客户信息修改失败: {}", ex);
            resDto.setResultMsg("报备客户信息修改失败：" + ex.getMessage());
        }
        return resDto;
    }

    /**
     * 角色权限控制
     *  1、是否展示报备客户全号
     *  2、是否展示经纪人号码
     * @param reqDto
     * @param cpDto
     * @return
     */
    private CustomerPremisesDto roleControlCustomerMobile(GetCPDetailReqDto reqDto, CustomerPremisesDto cpDto) {
        // 根据异常信息判断: undefined.需要从前端定位传值是否有问题
        if(StringUtils.isBlank(reqDto.getUserId()) || StringUtils.equals("undefined", reqDto.getUserId())){
            return cpDto;
        }
        PartnerInfo loginUser = partnerInfoService.selectById(Long.parseLong(reqDto.getUserId()));
        if (PartnerInfoEnum.ACCOUNT_MECHANISM.getCode().equals(loginUser.getAccountType())) {
            return cpDto;
        }
        List<String> codes = Lists.newArrayList();
        codes.add("menu_0005_0001_0015");
        codes.add("menu_0008_0006");
        codes.add("menu_0005_0001_0020");
        codes.add("menu_0008_0007");
        List<RoleResources> roleResources = roleResourcesService.listRoleResources(loginUser.getUserRoleId(), codes);
        if (CollectionUtils.isEmpty(roleResources)) {
            return cpDto;
        }
        if (reqDto.getLoginType().equals(SystemIdEnum.DEVELOPERS.getCode())) {
            for (RoleResources roleResource : roleResources) {
                if (StringUtils.equals(roleResource.getResourcesCode(), "menu_0005_0001_0015")) {
                    cpDto.setShowFullNumber(Boolean.FALSE);
                }
                if (StringUtils.equals(roleResource.getResourcesCode(), "menu_0005_0001_0020")) {
                    cpDto.setHideAgentPhone(Boolean.TRUE);
                }
            }
        } else if (reqDto.getLoginType().equals(SystemIdEnum.ASSISTANT.getCode()) || reqDto.getLoginType().equals(SystemIdEnum.APP_ASSISTANT.getCode())) {
            for (RoleResources roleResource : roleResources) {
                if (StringUtils.equals(roleResource.getResourcesCode(), "menu_0008_0006")) {
                    cpDto.setShowFullNumber(Boolean.FALSE);
                }
                if (StringUtils.equals(roleResource.getResourcesCode(), "menu_0008_0007")) {
                    cpDto.setHideAgentPhone(Boolean.TRUE);
                }
            }
        }
        return cpDto;
    }

    @Override
    public GetCPDetailResDto getCPDetail(GetCPDetailReqDto reqDto) {
        GetCPDetailResDto resDto = new GetCPDetailResDto();
        resDto.setResult(ResultEnum.FAIL.getNo());
        try {
            CustomerPremisesDto cpDto = customerPremisesService.selectByMyId(Long.valueOf(reqDto.getId()));
            if(Objects.isNull(cpDto)){
                return resDto;
            }
            // 角色权限控制是否展示报备客户全号
            roleControlCustomerMobile(reqDto, cpDto);
            cpDto.setMobileHidden(Boolean.FALSE);
            if (cpDto.getShowFullNumber() != null
                    && StringUtils.isNotEmpty(cpDto.getMobile())
                    && cpDto.getMobile().indexOf(StringConstant.THREE_STAR) < 0
                    && Boolean.FALSE.equals(cpDto.getShowFullNumber())) {
                cpDto.setMobile(ReportWayEnum.convertMobileByReportWay(cpDto.getMobile(), ReportWayEnum.BEFORE_THREE_AFTER_FOUR.getNo()));
                cpDto.setMobileHidden(Boolean.TRUE);
            }
			//代报备时，案场人员的名字不会为空
			if(StringUtils.isNotBlank(cpDto.getAssistantName())){
				cpDto.setReportType("案场代报备");
			}else{
				cpDto.setReportType("经纪人报备");
				if (StringUtils.isNotBlank(cpDto.getReportPhone())){
					cpDto.setStaffPhone(cpDto.getReportPhone());
				}
			}
            if(Objects.nonNull(cpDto.getHideAgentPhone()) && Boolean.TRUE.equals(cpDto.getHideAgentPhone())){
                cpDto.setStaffPhone(ReportWayEnum.convertMobileByReportWay(cpDto.getStaffPhone(), ReportWayEnum.BEFORE_THREE_AFTER_FOUR.getNo()));
            }
			cpDto.setGenderCN("");
			if(GenderEnum.MALE.getNo().equals(cpDto.getGender())){
				cpDto.setGenderCN("先生");
			}else if(GenderEnum.FEMALE.getNo().equals(cpDto.getGender())){
				cpDto.setGenderCN("女士");
			}
            cpDto.setConfirmStatusName(ConfirmStatusEnum.payDeposit.getDes());
			if (StringUtils.isNotEmpty(cpDto.getConfirmStatus())) {
				cpDto.setConfirmStatusName(ConfirmStatusEnum.getByNo(
                cpDto.getConfirmStatus()).getDes());
			}
            // 没有预计到访时间,不设置默认值
			//if(Objects.isNull(cpDto.getHopeVisitTime())){
            //    cpDto.setHopeVisitTime(cpDto.getCreateTime());
            //}
            //cpDto.setFormatHopeVisitTime(DateUtils.DateToString(cpDto.getHopeVisitTime(), DateStyle.YYYY_MM_DD_HH_MM_SS));

			//推荐人
            cpDto.setRecommenderName("");
            cpDto.setRecommenderDeptName("");
			if(StringUtils.isNotBlank(cpDto.getRecommenderUuid())){
				PremisesRecommenderDto dto = premisesRecommenderService.getPremisesRecommenderByUuid(cpDto.getRecommenderUuid());
				cpDto.setRecommenderName(dto.getUserName());
				cpDto.setRecommenderDeptName(dto.getDeptName());
			}

			if(StringUtils.isNotBlank(cpDto.getCustomerStatus())){
				cpDto.setCustomerStatusName(CustomerStatusEnum.getByNo(cpDto.getCustomerStatus()).getDes());
			}
			if(null != cpDto.getCreateTime()){
				cpDto.setCreateTime(cpDto.getCreateTime());
			}
			cpDto.setRemark(cpDto.getRemark());

			//计算带看保护时间
			Date visitProtectTime = cpDto.getVisitProtectTime();
			Calendar calendar = Calendar.getInstance();
			//默认报备: 非带看保护期中......
			cpDto.setVisitProtecting(false);
			//判断是否特殊报备: 特殊报备记录,皆为非带看保护中记录....
			String reportType = cpDto.getReportType();
			if(StringUtils.isEmpty(reportType) ||
					ReportTypeEnum.type_1.getNo().equals(reportType)){
				if(null != visitProtectTime){
					//比较带看保护时间是否大于当前时间
					//大于当前时间: 带看保护中 小于当前时间: 已过保护时间,可操作记录
					if(visitProtectTime.compareTo(calendar.getTime()) > 0){
						cpDto.setVisitProtecting(true);
					}
				}
			}
			SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			if(cpDto.getHopeVisitTime() != null){
				cpDto.setVisitProtecDate(sdf1.format(cpDto.getHopeVisitTime()));
			}else if(cpDto.getVisitProtectTime() != null){
				// 2020-9-28: 不设置默认值
			    //cpDto.setVisitProtecDate(sdf1.format(cpDto.getVisitProtectTime()));
			}

			FollowUpListDto fulDto = new FollowUpListDto();
			fulDto.setCustomerPremisesId(Long.valueOf(reqDto.getId()));
			fulDto.setOrders("t.create_time desc");
			// 非渠道或总代公司不能查看内部跟进类型
			if (!reqDto.getLoginType().equals(SystemIdEnum.DEVELOPERS.getCode())
					&& !reqDto.getLoginType().equals(SystemIdEnum.ADMIN.getCode())
					&& !reqDto.getLoginType().equals(SystemIdEnum.ASSISTANT.getCode())
					&& !reqDto.getLoginType().equals(SystemIdEnum.APP_ASSISTANT.getCode())) {
				fulDto.setFollowTypes("1,2");
			}
			List<FollowUpList> fulList = followUpListService.selectListByDto(fulDto);
			List<FollowUpList> repeatVisitFollow = new ArrayList<>();
			int visitState = 0;
			if(StringUtils.isNotBlank(cpDto.getVisitState())){
				visitState = Integer.valueOf(cpDto.getVisitState());
			}

            List<Long> partnerIds = new ArrayList<>();
            partnerIds.add(cpDto.getPartnerId());
            partnerIds.add(cpDto.getPrincipalId());
            fulList.forEach(item -> {
                partnerIds.add(item.getStaffId());
            });
            PartnerInfoDto piDto = new PartnerInfoDto();
            piDto.setIds(partnerIds);
            List<PartnerInfo> piList = partnerInfoService.selectListByDto(piDto);
            Map<Long, PartnerInfo> piMap = piList.stream().collect(Collectors.toMap(PartnerInfo::getId, Function.identity()));
            cpDto.setIsDist("F");
            PartnerInfo partnerInfo = piMap.get(cpDto.getPartnerId());
            if(Objects.nonNull(partnerInfo)){
                cpDto.setIsDist("T");
                cpDto.setAssistantName(partnerInfo.getAccountName());
                cpDto.setAssistantPhone(partnerInfo.getPhone());
            }
            partnerInfo = piMap.get(cpDto.getPrincipalId());
            if(Objects.nonNull(partnerInfo)){
                cpDto.setPrincipalName(partnerInfo.getAccountName());
                cpDto.setPrincipalPhone(partnerInfo.getPhone());
            }

			for (FollowUpList followUp : fulList) {
				partnerInfo = piMap.get(followUp.getStaffId());
				if (Objects.nonNull(partnerInfo)) {
					followUp.setStaffName(partnerInfo.getAccountName());
				}
				if(StringUtils.isNotEmpty(followUp.getRemark())){
					if (followUp.getRemark().indexOf("申请带看") != -1) {
						SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
						followUp.setCreateTime(df.parse(followUp.getApplyLookDay()));
					}
				}
				if(visitState > 1 && Objects.nonNull(followUp.getVisitedCount()) && Objects.nonNull(followUp.getVisitTime())
						&& followUp.getVisitedCount().intValue() > 1
						&& followUp.getVisitedCount().intValue() <= visitState){
					repeatVisitFollow.add(followUp);
				}
			}
			repeatVisitFollow = repeatVisitFollow.stream().sorted(Comparator.comparing(FollowUpList::getVisitTime)).collect(Collectors.toList());
			resDto.setRepeatVisitFollow(repeatVisitFollow);
			cpDto.setFulList(fulList);
			// 获取报备状态和亮灯数
            CustomerPremises customerPremises = new CustomerPremises();
            BeanUtils.copyProperties(cpDto, customerPremises);
			Map<String,String> map = customerPremisesService.getCusStatus(customerPremises);
			cpDto.setCurrentStatusMap(map);
			List<CustomerPremisesAffixDto> affixList=affixService.listAffixByAffixType(Long.valueOf(reqDto.getId()),AffixTypeEnum.FIRST_PAYMENT.toString());
			cpDto.setAffixList(affixList);

			//获取约看信息
			ReportVisitDto reportVisit = new ReportVisitDto();
			reportVisit.setReportId(cpDto.getId());
			reportVisit.setIsDeleted(DelFlagEnum.UNDEL.getNo());
			reportVisit.setOrders(" create_time desc ");
			List<ReportVisit> reportVisitList = reportVisitService.selectListByDto(reportVisit);
			if(reportVisitList !=null && reportVisitList.size() != 0){
				resDto.setReportVisit(reportVisitList.get(0));
			}

			// 报备置业顾问
			if(StringUtils.isNotBlank(cpDto.getAdviserUuid())){
				EstateAdviser estateAdviser = estateAdviserService.getAdviserByUuid(cpDto.getAdviserUuid());
				resDto.setEstateAdviser(estateAdviser);
			}
			// 客户明细
			CustomerInfoDto customerInfoDto = new CustomerInfoDto();
			customerInfoDto.setCpId(cpDto.getId());
			CustomerInfo customerInfo = customerInfoService.selectByDto(customerInfoDto);
			resDto.setCustomerInfo(customerInfo);

			// 报备佣金
			ReportCommissionDto rcdto = new ReportCommissionDto();
			rcdto.setDelFlag(DelFlagEnum.UNDEL.getNo());
			rcdto.setReportId(cpDto.getId());
			ReportCommission reportCommission = reportCommissionService.selectOne(rcdto);
			resDto.setReportCommission(reportCommission);

            // 报备复制次数
            List<Long> reportIds = Arrays.asList(cpDto.getId());
            ReportCopyRecordDto rcrDto = new ReportCopyRecordDto();
            if(StringUtils.isNotEmpty(reqDto.getUserId()) && !"null".equals(reqDto.getUserId())) {
            	rcrDto.setCopyUser(Long.valueOf(reqDto.getUserId()));
            }
            rcrDto.setReportIds(reportIds);
            List<ReportCopyRecordDto> rcrDtoList = reportCopyRecordService.selectCopyCountByReport(rcrDto);
            cpDto.setCopyCount(0);
            if(!CollectionUtils.isEmpty(rcrDtoList)){
                cpDto.setCopyCount(rcrDtoList.get(0).getCopyCount());
            }

			resDto.setCpDto(cpDto);
			resDto.setResult(ResultEnum.SUCCESS.getNo());
		}catch(Exception ex) {
			logger.error("获取报备详情失败: {}", ex);
			resDto.setResultMsg("获取报备详情失败: " + ex.getMessage());
		}
		return resDto;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public AddAppealResDto addAppeal(AddAppealReqDto reqDto, String assistantAccessToken) {
		AddAppealResDto res = new AddAppealResDto();
		res.setResult(ResultEnum.FAIL.getNo());
		Long cusPremisesId =  reqDto.getCusPremisesId();
		Long staffId =reqDto.getStaffId();
		String remark = reqDto.getRemark();
		String result = customerPremisesService.reSubmit(reqDto.getAccountType(),cusPremisesId, staffId, remark);
		if("0".equals(result)){
			//发送短信
			CustomerPremises cusPre = customerPremisesService.selectById(cusPremisesId);
			//查询楼盘相关案场助手人员,发短信用
	    	CaseMemberDto cmDto = new CaseMemberDto();
	    	cmDto.setPremisesId(cusPre.getPremisesId());
			cmDto.setSmsStatus("1");
	    	List<CaseMember> cmList = caseMemberService.selectListByDto(cmDto);
			if(null != cmList && cmList.size() > 0){
				//报备人
				PartnerInfo pi = partnerInfoService.selectById(staffId);
				//报备记录
				CustomerPremises cp = customerPremisesService.selectById(cusPremisesId);
				//报备客户,给楼盘对应的管理员发送短信
	        	String smsSwitch = smsUtil.getSmsSwitch();
	        	smsSwitch = "F"; //短信关闭,临时处理方案 JHSong
	        	if(org.apache.commons.lang.StringUtils.isNotEmpty(smsSwitch) && "T".equals(smsSwitch)){
	        		String smsTemp = SMSTypeEnum.TYPE_02.getNo();
	        		DictionaryDto dicDto = new DictionaryDto();
	        		dicDto.setDicType(smsTemp);
	        		Dictionary dic = dictionaryService.selectByDto(dicDto);
	        		if(null != dic){
	        			for(CaseMember cm: cmList){
	        				String premisesName = cm.getPremisesName();
		        			String cusName = cp.getName();
		        			String reportName = pi.getAccountName();
		        			String receiveMobile = "";
		        			PartnerInfo cmPi = partnerInfoService.selectById(cm.getPartnerId());
		        			if(null != cmPi){
		        				receiveMobile = cmPi.getPhone();
		        			}
		        			String smsContent = dic.getDicValue();
		        			smsContent = String.format(smsContent, premisesName, cusName, reportName, remark);
		        		//	boolean sendStatus = smsUtil.sendMessage(smsContent, receiveMobile);
		        			boolean sendStatus = false;
		        			SmsHistoryDto smsHis = new SmsHistoryDto();
		        			smsHis.setSender(smsUtil.getUserName());
		        			smsHis.setReceiver(receiveMobile);
		        			smsHis.setContent(smsContent);
		        			smsHis.setSendStatus(sendStatus?SendStatusEnum.SUCCESS.getNo():SendStatusEnum.FAILURE.getNo());
		        			smsHis.setMerchantId(cmPi.getHigherid());
		        			smsHis.setRemark("经纪人申诉");
		        			smsHis.setCreateUserId(pi.getId());

		        			smsHistoryService.create(smsHis);
	        			}
	        		}
	    		}
			}
            //通知驻场人员审核
            wxTemplateMsgService.sendReportAppealTemplateMsg(assistantAccessToken, reqDto.getCompanyUuid()
                    , reqDto.getDomain(), cusPre.getId(), cusPre.getPremisesId() + "", reqDto.getStaffId() + ""
                    , cusPre.getName(), cusPre.getMobile(), cusPre.getHopeVisitTime() == null ? "" :DateUtils.DateToString(cusPre.getHopeVisitTime(), DateStyle.YYYY_MM_DD_HH_MM_SS));
            res.setResult(ResultEnum.SUCCESS.getNo());
            res.setResultMsg("操作成功");
        } else if ("-2".equals(result)) {
            res.setResultMsg("不能发起非本人客户的申诉!");
            res.setResult(ResultEnum.FAIL.getNo());
        } else if ("-3".equals(result)) {
            res.setResultMsg("申诉只能发起一次，您已经发起过，不能再次发起！");
            res.setResult(ResultEnum.FAIL.getNo());
        }
        return res;
    }

    @Override
    public UpdateSaleStatusResDto updateSaleStatusHander(UpdateSaleStatusReqDto reqDto, CustomerPremisesDto customerPremisesDto, String agencyAccessToken, String assistantAccessToken) {
        ChangeCPConfirmReqDto changeCPConfirmReqDto = new ChangeCPConfirmReqDto();
        changeCPConfirmReqDto.setId(reqDto.getRecommendedChannelId());
        changeCPConfirmReqDto.setBuildingName(reqDto.getBuildingName());
        changeCPConfirmReqDto.setConfirmStatus(reqDto.getTransStatus());
        changeCPConfirmReqDto.setDealAmount(reqDto.getTotalAmount());
        changeCPConfirmReqDto.setRoomName(reqDto.getRoomName());
        changeCPConfirmReqDto.setValuationArea(reqDto.getCalArea());
        changeCPConfirmReqDto.setCompanyUuid(customerPremisesDto.getCompanyUuid());
        changeCPConfirmReqDto.setRemark("M2同步");

        // M2请求过来无当前登录人，取当前开发商管理员账号（升序第一个）
        PartnerInfoDto partnerInfoDto = new PartnerInfoDto();
        partnerInfoDto.setHigherid(customerPremisesDto.getCompanyId());
        List<PartnerInfo> piList = partnerInfoService.selectListByDto(partnerInfoDto);
        if (piList != null && piList.size() > 0) {
            changeCPConfirmReqDto.setUserId(piList.get(0).getId().toString());
        }

        //提前校验是否是重复操作
        UpdateSaleStatusResDto resDto = new UpdateSaleStatusResDto();
        CustomerPremises cusPre = customerPremisesService.selectByIdForLock(Long.valueOf(changeCPConfirmReqDto.getId()));
        if (cusPre.getConfirmStatus().equals(changeCPConfirmReqDto.getConfirmStatus())) {
            resDto.setResultMsg("操作重复，请刷新之后进行操作！");
            return resDto;
        }
        //M2同步置业顾问，成交客户信息
        logger.info("M2UpdateSaleStatusHander request info {}", JSONObject.toJSONString(reqDto));
        reportCommonService.syncM2DealInfo(reqDto, customerPremisesDto);

        ChangeCPConfirmResDto changeCPConfirmResDto = auditReportService.changeCPConfirm(changeCPConfirmReqDto, agencyAccessToken, assistantAccessToken);
        resDto.setResult(changeCPConfirmResDto.getResult());
        resDto.setResultMsg(changeCPConfirmResDto.getResultMsg());
        return resDto;
    }

    @Override
    public BatchReportResDto checkBatchReport(BatchReportReqDto params) throws ParseException {
        BatchReportResDto res = new BatchReportResDto();
        List<ReportInfo> reportInfoList = params.getReportInfoList();
        res.setResult(ResultEnum.SUCCESS.getNo());
        for (ReportInfo reportInfo : reportInfoList) {
            reportInfo.setStatus("0");
            reportInfo.setIfSelect("1");
            if (reportInfo.getRecommender() != null && reportInfo.getRecommender().length() > 0) {
                PremisesRecommenderDto recommender = premisesRecommenderService.getPremisesRecommenderByUuid(reportInfo.getRecommender());
                reportInfo.setRecommender(recommender.getUserName());
            }
            // 最短报备时间校验
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            Calendar calendar = Calendar.getInstance();
            String hopeTime = reportInfo.getHopeVisitTime();
            if (StringUtils.isBlank(hopeTime)) {
                reportInfo.setErrorMsg("期望带看时间不能为空");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }
            Long premisesId = reportInfo.getPremisesId();
            if (premisesId == null || premisesId == 0) {
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg("报备楼盘不能为空");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }
            Long hopeTimes = sdf.parse(hopeTime).getTime();
            if (hopeTimes < calendar.getTime().getTime()) {
                reportInfo.setErrorMsg("期望带看时间不能小于系统当前时间");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }

            Premises premises = premisesService.selectSimpleById(reportInfo.getPremisesId());
            if (Objects.isNull(premises)) {
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg("该楼盘不存在或已被删除");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }
            //最短报备时间限制
            if (premises.getSpecialTimeType() != null && !TimeUnitTypeEnum.NONE.getNo().equals(premises.getSpecialTimeType())) {
                String specialTime = premises.getSpecialTime();
                //该数据存入数据库的时候已经转为分钟，这里无需再转
                calendar.add(Calendar.MINUTE, +Integer.parseInt(specialTime));
                Long specialTimeS = calendar.getTime().getTime();
                if (hopeTimes < specialTimeS) {
                    reportInfo.setErrorMsg("该楼盘不支持临时报备，请按照要求提前报备");
                    res.setResult(ResultEnum.FAIL.getNo());
                    continue;
                }
            }

            if (null == premises || DelFlagEnum.DEL.getNo().equals(premises.getDelFlag())) {
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg("楼盘已无效，无法报备");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }
            if (SaleStatusEnum.type_3.getNo().equals(premises.getSaleStatus())) {
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg("楼盘已下架，无法报备");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }

            PartnerInfo agentPi = partnerInfoService.selectById(Long.parseLong(params.getStaffId()));
            if (null == agentPi) {
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg("经纪人不存在,无法报备");
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }

            //查看经纪人所属渠道商是否与M2绑定
            Company devCompany =  companyService.selectById(premises.getCompanyId());
            String mobile = params.getMobile();

            if (!RegexUtil.isMobileNumber(mobile) && mobile.indexOf(StringConstant.THREE_STAR) < 0) {
                String errorMsg = "手机号:" + mobile + "格式错误";
                reportInfo.setIfSelect("0");
                reportInfo.setErrorMsg(errorMsg);
                res.setResult(ResultEnum.FAIL.getNo());
                continue;
            }

            //报备方式
            if (StringUtils.equals(ReportWayEnum.FULL_NUMBER.getNo(), premises.getReportWay())) {
                if (mobile.contains(StringConstant.THREE_STAR)) {
                    String errorMsg = "该楼盘不支持隐号报备";
                    reportInfo.setIfSelect("0");
                    reportInfo.setErrorMsg(errorMsg);
                    res.setResult(ResultEnum.FAIL.getNo());
                    continue;
                }
            } else {
            	if(!ReportWayEnum.checkMobile(mobile, premises.getReportWay())) {
                	String errorMsg = "手机号:" + mobile + "，报备失败，楼盘仅支持：" + ReportWayEnum.getDescByNo(premises.getReportWay() + "方式报备");
                    reportInfo.setIfSelect("0");
                    reportInfo.setErrorMsg(errorMsg);
                    res.setResult(ResultEnum.FAIL.getNo());
                    continue;
            	}
            }
            ReportProtectOverDueDto reportProtectOverDueDto = null;
            ReportValidOverDueDto reportValidOverDueDto = null;
            if (!mobile.contains(StringConstant.THREE_STAR)) {
                //2.已到访客户 的客户不能再进行报备
                boolean visitFlag = customerPremisesService.checkVisitRepeat(0L, premises, mobile);
                if (visitFlag) {
                    String errorMsg = "客户已到访该楼盘,无法再次报备";
                    reportInfo.setIfSelect("0");
                    reportInfo.setErrorMsg(errorMsg);
                    res.setResult(ResultEnum.FAIL.getNo());
                    continue;
                }

                // 3、报备保护逾期校验
                // 3.1、判断能否报备--> 不能时返回
                // 3.2、能报备: 判断保护时间应该是多久~
                reportProtectOverDueDto = premisesOverdueService.checkReportProtect(premises, agentPi, mobile);
                logger.info("cpreportserviceimpl --> reportProtectOverDueDto: {}", JSONObject.toJSONString(reportProtectOverDueDto));
                if (!reportProtectOverDueDto.getCanReport().booleanValue()) {
                    String errorMsg = "手机号为【" + mobile + "】的客户在此楼盘处于报备保护期内，目前不可报备<br/>";
                    reportInfo.setIfSelect("0");
                    reportInfo.setErrorMsg(errorMsg);
                    res.setResult(ResultEnum.FAIL.getNo());
                    continue;
                }

                // 报备有效逾期校验
                reportValidOverDueDto = premisesOverdueService.checkReportValid(premises, agentPi, mobile);
                logger.info("cpreportserviceimpl --> reportValidOverDueDto: {}", JSONObject.toJSONString(reportValidOverDueDto));
                if (!reportValidOverDueDto.getCanReport().booleanValue()) {
                    String errorMsg = "报备无效次数过多,目前不可报备<br/>";
                    reportInfo.setErrorMsg(errorMsg);
                    continue;
                }
                // 校验手机号在M2的唯一性
                if (ReportExternalConvert.repeatSwitchForM2(devCompany, premises.getProjectCodeM2())) {
                    CommonResDTO commonResDto = reportCommonService.isExistsInM2(premises.getProjectCodeM2(), devCompany.getMerchantCode(), mobile, m2ApiConfig.getM2RequestUrl());
                    if (ResultEnum.FAIL.getNo().equals(commonResDto.getResult())) {
                        String errorMsg = "该客户已录入于M2系统该楼盘下";
                        reportInfo.setIfSelect("0");
                        reportInfo.setErrorMsg(errorMsg);
                        res.setResult(ResultEnum.FAIL.getNo());
                        continue;
                    }
                }
            }
            reportInfo.setStatus("1");
        }
        res.setBatchReportInfo(reportInfoList);
        return res;
    }

    @Override
    public AddBatchReportResDto addBatchReport(BatchReportReqDto params, String assistantAccessToken) {
        AddBatchReportResDto resDto = new AddBatchReportResDto();
        CustomerPremisesDto cpDto = new CustomerPremisesDto();
        List<ReportInfo> reportInfoList = params.getReportInfoList();
        int saveReportCount = 0;
        int reportSize = reportInfoList.size();
        List<AddBatchReportResultDto> batchResultList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        for (ReportInfo reportInfo : reportInfoList) {
        	Long premisesId = reportInfo.getPremisesId();
            Premises premises = premisesService.selectSimpleById(premisesId);
            
            //记录返回值
        	AddBatchReportResultDto batchResult = new AddBatchReportResultDto();
            batchResult.setFlag(Boolean.FALSE);
            batchResult.setPremisesId(premises.getId());
            batchResult.setPremisesName(premises.getName());
            
            String mobile = params.getMobile();
            
            //如果传入是隐号，则判断传入的隐号是否符合当前报备规则。如果传入进来为全号，会按照楼盘规则在下方进行转换
            if(mobile.contains(StringConstant.THREE_STAR)) {
            	if(!premisesService.checkMobileByPremises(mobile, premisesId)) {
                	String errorMsg = "mobile:" + mobile + ",不符合当前楼盘的报备方式:reportWay=" + ReportWayEnum.getDescByNo(premises.getReportWay());
                    batchResult.setErrorMsg(errorMsg);
                    batchResultList.add(batchResult);
                    continue;
                }
            }

            //查看经纪人所属渠道商是否与M2绑定
            Company devCompany =  companyService.selectById(premises.getCompanyId());
            if (ReportExternalConvert.repeatSwitchForM2(devCompany, premises.getProjectCodeM2())) {
                // 校验手机号在M2的唯一性
                CommonResDTO commonResDto = reportCommonService.isExistsInM2(premises.getProjectCodeM2(), devCompany.getMerchantCode(), mobile, m2ApiConfig.getM2RequestUrl());
                if (ResultEnum.FAIL.getNo().equals(commonResDto.getResult())) {
                    String errorMsg = "保护期内，无法报备";
                    if(reportSize == 1){
                        errorMsg = "该客户在" + errorMsg;
                    }
                    batchResult.setErrorMsg(errorMsg);
                    batchResultList.add(batchResult);
                    continue;
                }
            }

            //增加客户手机号码全号唯一验证
            if(StringUtils.equals(ReportWayEnum.UNLIMITED.getNo(), premises.getReportWay()) &&  mobile.indexOf(StringConstant.THREE_STAR) < 0){
                //验证手机号码是否存在
                CustomerPremises dataResult = customerPremisesService.selectByMobile(mobile);
                if(dataResult != null){
                    String errorMsg = "手机号:" + mobile + "，已存在，" + ReportWayEnum.getDescByNo(ReportWayEnum.FULL_NUMBER.getNo());
                    batchResult.setErrorMsg(errorMsg);
                    batchResultList.add(batchResult);
                    continue;
                }
            }


            //增加客户手机号码前三后四验证
            if(StringUtils.equals(ReportWayEnum.UNLIMITED.getNo(), premises.getReportWay())  &&  mobile.indexOf(StringConstant.THREE_STAR) >=0 ){
                String mobleValue = mobile.substring(0,2)+"%%"+mobile.substring(7,10);
                //验证手机号码是否存在
                CustomerPremises dataResult = customerPremisesService.selectByMobile(mobleValue);
                if(dataResult != null){
                    String errorMsg = "手机号:" +  mobile + "，已存在，" + ReportWayEnum.getDescByNo(ReportWayEnum.BEFORE_THREE_AFTER_FOUR.getNo());
                    batchResult.setErrorMsg(errorMsg);
                    batchResultList.add(batchResult);
                    continue;
                }
            }

            // 隐号报备,若传入全号手机号,直接将手机号改为隐号
            if(!ReportWayEnum.UNLIMITED.getNo().equals(premises.getReportWay())
                    && !ReportWayEnum.FULL_NUMBER.getNo().equals(premises.getReportWay()) && !mobile.contains(StringConstant.THREE_STAR)){
                mobile = premisesService.convertMobileByPremises(mobile, premises.getId());
            }
            
            try {
                PartnerInfo assistantPi = partnerInfoService.selectById(Long.parseLong(params.getUserId()));
                PartnerInfo agentPi = partnerInfoService.selectById(Long.parseLong(params.getStaffId()));
                ReportProtectOverDueDto reportProtectOverDueDto = null;
                ReportValidOverDueDto reportValidOverDueDto = null;

                //最短报备时间限制
                Calendar calendar = Calendar.getInstance();
                Date hopeVisitTime = null;
                if(StringUtils.isNotBlank(reportInfo.getHopeVisitTime())){
                	hopeVisitTime = sdf.parse(reportInfo.getHopeVisitTime());
                }
                if (premises.getSpecialTimeType() != null && !TimeUnitTypeEnum.NONE.getNo().equals(premises.getSpecialTimeType())) {
                    String specialTime = premises.getSpecialTime();
                    //该数据存入数据库的时候已经转为分钟，这里无需再转
                    calendar.add(Calendar.MINUTE, +Integer.parseInt(specialTime));
                    Long specialTimeS = calendar.getTime().getTime();
                    if (hopeVisitTime != null && hopeVisitTime.getTime() < specialTimeS) {
                        String errorMsg = "不符合楼盘最短报备时间要求";
                        batchResult.setErrorMsg(errorMsg);
                        batchResultList.add(batchResult);
                        continue;
                    }
                }

                if (!mobile.contains(StringConstant.THREE_STAR)) {
                    // 1.楼盘 + 手机号 + 到访 + (交易待定、认筹、认购) 存在记录不能报备
                    boolean visitFlag = customerPremisesService.checkVisitRepeat(0L, premises, mobile);
                    if (visitFlag) {
                        // String errorMsg = "手机号为【" + mobile + "】的客户已到访该楼盘,无法再次报备!";
                        String errorMsg = "保护期内，无法报备";
                        if(reportSize == 1){
                            errorMsg = "该客户在" + errorMsg;
                        }
                        batchResult.setErrorMsg(errorMsg);
                        batchResultList.add(batchResult);
                        continue;
                    }

                    // 2、报备保护逾期校验
                    // 2.1、判断能否报备--> 不能时返回
                    // 2.2、能报备: 判断保护时间应该是多久~
                    reportProtectOverDueDto = premisesOverdueService.checkReportProtect(premises, agentPi, mobile);
                    logger.info("cpreportserviceimpl --> reportProtectOverDueDto: {}", JSONObject.toJSONString(reportProtectOverDueDto));
                    if (!reportProtectOverDueDto.getCanReport().booleanValue()) {
                        // String errorMsg = "手机号为【" + mobile + "】的客户在此楼盘处于报备保护期内，目前不可报备<br/>";
                        String errorMsg = "保护期内，无法报备";
                        if(reportSize == 1){
                            errorMsg = "该客户在" + errorMsg;
                        }
                        batchResult.setErrorMsg(errorMsg);
                        batchResultList.add(batchResult);
                        continue;
                    }

                    // 报备有效逾期校验
                    reportValidOverDueDto = premisesOverdueService.checkReportValid(premises, agentPi, mobile);
                    logger.info("cpreportserviceimpl --> reportValidOverDueDto: {}", JSONObject.toJSONString(reportValidOverDueDto));
                    if (!reportValidOverDueDto.getCanReport().booleanValue()) {
                        // String errorMsg = "报备无效次数过多,目前不可报备";
                        String errorMsg = "保护期内，无法报备";
                        if(reportSize == 1){
                            errorMsg = "该客户在" + errorMsg;
                        }
                        batchResult.setErrorMsg(errorMsg);
                        batchResultList.add(batchResult);
                        continue;
                    }

                }

                //添加报备信息
                cpDto.setCommissionWay(premises.getCommissionWay());
                cpDto.setStaffId(Long.parseLong(params.getStaffId()));
                cpDto.setPremisesId(reportInfo.getPremisesId());
                cpDto.setMobile(mobile);
                cpDto.setName(params.getName());
                cpDto.setGender(params.getGender());
                cpDto.setConfirmStatus(ConfirmStatusEnum.confirm.getNo());

                cpDto.setCustomerStatus(CustomerStatusEnum.normal.getNo());
                cpDto.setRemark(params.getRemark());
                cpDto.setCompanyId(premises.getCompanyId());
                cpDto.setStaffCompanyId(agentPi.getHigherid());
                //1:已收房源、2: 海外房源
                cpDto.setPremisesSource(premises.getFromSource());
                cpDto.setCommissionAmount("0");
                cpDto.setReward(StringUtils.isEmpty(premises.getReward()) == true ? new BigDecimal("0") : new BigDecimal(premises.getReward()));
                cpDto.setDomesticProportion(String.valueOf(premises.getZjCommissionRatio()));
                cpDto.setComplaintsNumber(0L);

                //报备保护时长
                reportCommonService.setReportProtectOverDueTime(cpDto, reportProtectOverDueDto);
                //报备有效时长
                reportCommonService.setReportValidOverDueTime(cpDto, reportValidOverDueDto);
                //待看保护时长
                String saveDays = premises.getSaveDays();
                calendar = Calendar.getInstance();
                if (StringUtils.isNotEmpty(saveDays)) {
                    try {
                        calendar.add(Calendar.MINUTE, Integer.parseInt(saveDays));
                        cpDto.setLookPeriodTime(calendar.getTime());
                    } catch (Exception e) {
                        cpDto.setLookPeriodTime(calendar.getTime());
                    }
                }
                cpDto.setLongitude(premises.getLongitude());
                cpDto.setLatitude(premises.getLatitude());
                cpDto.setReportType(params.getReportType());

                //带看保护时间
                Calendar visitProtectCalendar = customerPremisesService.getVisitProtectCalendar(reportInfo.getPremisesId(), premises.getVisitProtect());
                cpDto.setVisitProtectTime(visitProtectCalendar.getTime());
                //期望带看保护时间
                cpDto.setHopeVisitTime(hopeVisitTime);
                Long principalId = customerPremisesService.getPricipalId(cpDto.getStaffId());
                cpDto.setPrincipalId(principalId);
                //报备手机号
                cpDto.setReportPhone(agentPi.getPhone());
                if (!TimeUnitTypeEnum.NONE.getNo().equals(premises.getSpecialTimeType()) && StringUtils.isNotBlank(premises.getSpecialTime())) {
                    calendar = Calendar.getInstance();
                    String specialTime = premises.getSpecialTime();
                    calendar.add(Calendar.MINUTE, Integer.parseInt(specialTime));
                    cpDto.setVisitPastTime(calendar.getTime());
                }
                //推荐人
                if (reportInfo.getRecommender() != null && reportInfo.getRecommender().length() > 0) {
                    cpDto.setRecommenderUuid(reportInfo.getRecommender());
                }
                if(StringUtils.isNotBlank(params.getCustomerId())){
                    cpDto.setCustomerId(Long.valueOf(params.getCustomerId()));
                }
                cpDto = customerPremisesService.create(cpDto);

                //写带状态跟进记录
                reportCommonService.addReportFollow(cpDto, FollowTypeEnum.CHANNEL.getNo(), "报备客户", String.valueOf(cpDto.getStaffId()), params.getRemark());

                //保存附件
                DocumentDto docDto = new DocumentDto();
                docDto.setObjectId(cpDto.getId());
                docDto.setType(Long.parseLong(DocumentTypeEnum.TYPE_1.getNo()));
                List<AddReportFileBean> fileList = params.getFileList();
                if (null != fileList && fileList.size() > 0) {
                    for (AddReportFileBean fileBean : fileList) {
                        docDto.setUrl(fileBean.getFileName());
                        documentService.create(docDto);
                    }
                }

                //添加自定义报备模板信息
                if (reportInfo.getReportModelList() != null && reportInfo.getReportModelList().size() > 0) {
                    reportModelApiService.setReportModeInfo(reportInfo.getReportModelList(), cpDto.getId());
                }

                //组装短信发送内容Map
                Map<String, String> smsMap = new HashMap<String, String>();
                smsMap.put("premisesName", premises.getName());
                Company company = companyService.selectById(agentPi.getHigherid());
                if (null != company) {
                    smsMap.put("agentCompany", company.getCompanyName());
                }
                Department dept = departmentDao.selectById(agentPi.getDeptId());
                if (null != dept) {
                    smsMap.put("agentDept", dept.getDepartmentName());
                }
                smsMap.put("agentName", agentPi.getAccountName());
                smsMap.put("agentPhone", agentPi.getPhone());
                smsMap.put("cusName", cpDto.getName());
                smsMap.put("mobile", mobile);
                //发送短信
                reportCommonService.sendReportSms(premises, assistantPi, smsMap, cpDto, "经纪人报备");
                //同步V10报备
                v10BindService.syncIntention(cpDto);
                SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //通知驻场人员审核
                wxTemplateMsgService.sendReportCheckTemplateMsg(assistantAccessToken, params.getCompanyUuid()
                        , null, cpDto.getId(), reportInfo.getPremisesId() + "", params.getStaffId()
                        , params.getName(), mobile, StringUtils.isBlank(reportInfo.getHopeVisitTime())?"":sdf1.format(sdf1.parse(reportInfo.getHopeVisitTime())));

                if (FreeAuditEnum.FREE_REPORT_AUDIT.getNo().equals(premises.getFreeAudit())) {
                    // 判断是否需要自动审核通过
                    AuditCPReqDto auditCPReqDto = new AuditCPReqDto();
                    auditCPReqDto.setId(String.valueOf(cpDto.getId()));
                    auditCPReqDto.setCustomerStatus(CustomerStatusEnum.not_visited.getNo());
                    auditCPReqDto.setRemark("报备免审");
                    auditCPReqDto.setUserId(String.valueOf(assistantPi.getId()));
                    auditCPReqDto.setLoginType(SystemIdEnum.DEVELOPERS.getCode());
                    auditCPReqDto.setCreateTime(null);
                    auditCPReqDto.setAffixList(null);
                    auditReportService.auditCP(auditCPReqDto, null, assistantAccessToken);
                }

                batchResult.setFlag(Boolean.TRUE);
                batchResult.setErrorMsg("报备成功");
                batchResultList.add(batchResult);
                saveReportCount++;
            } catch (Exception e) {
                logger.error("报备记录: {}, 报备异常: {}", reportInfo, e);
                String errorMsg = "信息有误，无法报备";
                if(reportSize == 1){
                    errorMsg = "该客户" + errorMsg;
                }
                batchResult.setErrorMsg(errorMsg);
                batchResultList.add(batchResult);
            }
        }
        resDto.setSaveReportCount(saveReportCount);
        resDto.setBatchResult(batchResultList);
        return resDto;
    }

    @Override
    public ExchangeHousesResDto exchangeHouses(ExchangeHousesReqDto reqDto, CustomerPremisesDto customerPremisesDto, String agencyAccessToken, String assistantAccessToken) {
        logger.info("M2案场换房 request: {}", JSONObject.toJSONString(reqDto));
        ExchangeHousesCPConfirmReqDto confirmReqDto = new ExchangeHousesCPConfirmReqDto();
        confirmReqDto.setId(reqDto.getRecommendedChannelId());
        confirmReqDto.setBuildingName(reqDto.getBuildingName());
        confirmReqDto.setConfirmStatus(reqDto.getTransStatus());
        confirmReqDto.setDealAmount(reqDto.getTotalAmount());
        confirmReqDto.setRoomName(reqDto.getRoomName());
        confirmReqDto.setValuationArea(reqDto.getCalArea());
        confirmReqDto.setCompanyUuid(customerPremisesDto.getCompanyUuid());
        confirmReqDto.setRemark("案场换房");

        // M2请求过来无当前登录人，取当前开发商管理员账号（升序第一个）
        PartnerInfoDto partnerInfoDto = new PartnerInfoDto();
        partnerInfoDto.setHigherid(customerPremisesDto.getCompanyId());
        List<PartnerInfo> piList = partnerInfoService.selectListByDto(partnerInfoDto);
        if (piList != null && piList.size() > 0) {
            confirmReqDto.setUserId(piList.get(0).getId().toString());
        }
        //M2同步置业顾问，成交客户信息
        logger.info("M2ExchangeHouses request info {}", JSONObject.toJSONString(reqDto));
        UpdateSaleStatusReqDto statusDto = new UpdateSaleStatusReqDto();
        BeanUtils.copyProperties(reqDto, statusDto);
        reportCommonService.syncM2DealInfo(statusDto, customerPremisesDto);

        ExchangeHousesResDto resDto = auditReportService.exchangeHousesCPConfirm(confirmReqDto, agencyAccessToken, assistantAccessToken);
        logger.info("M2案场换房 response: {}", JSONObject.toJSONString(resDto));
        return resDto;
    }

    @Override
    public UpdateSaleStatusResDto newUpdateSaleStatusHander(UpdateSaleStatusReqDto reqDto, CustomerPremisesDto customerPremisesDto, String agencyAccessToken, String assistantAccessToken) {
        logger.info("M2新交易状态同步请求参数: {}", JSONObject.toJSONString(reqDto));
        ChangeCPConfirmReqDto changeCPConfirmReqDto = new ChangeCPConfirmReqDto();
        changeCPConfirmReqDto.setId(reqDto.getRecommendedChannelId());
        changeCPConfirmReqDto.setBuildingName(reqDto.getBuildingName());
        changeCPConfirmReqDto.setConfirmStatus(reqDto.getTransStatus());
        changeCPConfirmReqDto.setDealAmount(reqDto.getTotalAmount());
        changeCPConfirmReqDto.setRoomName(reqDto.getRoomName());
        changeCPConfirmReqDto.setValuationArea(reqDto.getCalArea());
        changeCPConfirmReqDto.setCompanyUuid(customerPremisesDto.getCompanyUuid());
        changeCPConfirmReqDto.setRemark("M2同步");

        // M2请求过来无当前登录人，取当前开发商管理员账号（升序第一个）
        PartnerInfoDto partnerInfoDto = new PartnerInfoDto();
        partnerInfoDto.setHigherid(customerPremisesDto.getCompanyId());
        List<PartnerInfo> piList = partnerInfoService.selectListByDto(partnerInfoDto);
        if (piList != null && piList.size() > 0) {
            changeCPConfirmReqDto.setUserId(piList.get(0).getId().toString());
        }

        //提前校验是否是重复操作
        UpdateSaleStatusResDto resDto = new UpdateSaleStatusResDto();
        CustomerPremises cusPre = customerPremisesService.selectByIdForLock(Long.valueOf(changeCPConfirmReqDto.getId()));
        if (cusPre.getConfirmStatus().equals(changeCPConfirmReqDto.getConfirmStatus())) {
            resDto.setResultMsg("操作重复，请刷新之后进行操作！");
            return resDto;
        }
        //M2同步置业顾问，成交客户信息
        logger.info("M2NewUpdateSaleStatusHander request info {}", JSONObject.toJSONString(reqDto));
        reportCommonService.syncM2DealInfo(reqDto, customerPremisesDto);

        ChangeCPConfirmResDto changeCPConfirmResDto = auditReportService.newChangeCPConfirm(changeCPConfirmReqDto, agencyAccessToken, assistantAccessToken);
        logger.info("M2新交易状态同步返回状态: {}, 返回信息：{}",changeCPConfirmResDto.getResult(),changeCPConfirmResDto.getResultMsg());
        resDto.setResult(changeCPConfirmResDto.getResult());
        resDto.setResultMsg(changeCPConfirmResDto.getResultMsg());
        return resDto;
    }

    @Override
    public UpdateAdviserResDto m2ToUpdateAdviser(UpdateAdviserReqDto reqDto) {
        UpdateAdviserResDto resDto = new UpdateAdviserResDto();
        ChangeCPAdviserReqDto changeCPAdviserReqDto = new ChangeCPAdviserReqDto();
        //通过报备id获取报备信息
        CustomerPremises cp = customerPremisesService.selectById(Long.valueOf(reqDto.getRecommendedChannelId()));
        if (Objects.isNull(cp)){
            logger.error("m2ToUpdateAdviser  报备不存在reqDto{}",reqDto);
            resDto.setResult(ResultEnum.FAIL.getNo());
            resDto.setResultMsg("该报备不存在！");
            return resDto;
        }

        /**
         * 查询置业顾问是否存在
         */
        EstateAdviser adviser = new EstateAdviser();
        adviser.setPhone(reqDto.getAdviserPhone());
        adviser.setName(reqDto.getAdviserName());
        adviser.setPremisesId(cp.getPremisesId());
        EstateAdviser estateAdviser = estateAdviserService.selectOne(adviser);
        /**
         * 如果没有，插入一条
         */
        if (Objects.isNull(estateAdviser)){
            logger.info("m2ToUpdateAdviser  该人员不是本楼盘的置业顾问reqDto{} ,所以新增一条置业顾问信息",reqDto);
            estateAdviser = new EstateAdviser();
            estateAdviser.setName(reqDto.getAdviserName());
            estateAdviser.setPhone(reqDto.getAdviserPhone());
            estateAdviser.setPremisesId(cp.getPremisesId());
            estateAdviser.setAdviserUuid(UUID.randomUUID().toString());
            estateAdviser.setDeleted(DelFlagEnum.UNDEL.getNo());
            estateAdviserService.add(estateAdviser);
            logger.info("新增外部置业顾问{}",estateAdviser);
        }

        changeCPAdviserReqDto.setNewAdviser(estateAdviser.getAdviserUuid());
        changeCPAdviserReqDto.setCustomerPremisesId(cp.getId());
        changeCPAdviserReqDto.setPremisesId(cp.getPremisesId());
        changeCPAdviserReqDto.setOldAdviser(cp.getAdviserUuid());
        //更改置业顾问
        estateAdviserService.changeCPAdviser(changeCPAdviserReqDto);
        resDto.setResult(ResultEnum.SUCCESS.getNo());
        resDto.setResultMsg("变更置业顾问成功");
        logger.info("m2ToUpdateAdviser  置业顾问变更成功reqDto{}",reqDto);
        return resDto;
    }
}
